package com.ccys.cms.service.discount.impl;

import cn.hutool.core.util.ObjectUtil;
import com.ccys.cms.service.discount.BinNumberService;
import com.ccys.cms.service.discount.BinNumberServiceService;
import com.ccys.common.util.Kit;
import com.ccys.common.vo.ResponseResult;
import com.ccys.db.dto.discount.BinNumberDto;
import com.ccys.db.entity.TblBinNumber;
import com.ccys.db.entity.TblBinNumberService;
import com.ccys.db.entity.TblMedicalService;
import com.ccys.db.entity.TblPackage;
import com.ccys.db.mapper.TblBinNumberMapper;
import com.ccys.db.mapper.TblBinNumberServiceMapper;
import com.ccys.db.mapper.TblMedicalServiceMapper;
import com.ccys.db.mapper.TblPackageMapper;
import com.ccys.db.page.PageDto;
import com.ccys.db.rely.service.impl.BaseServiceImpl;
import com.ccys.db.service.BaseTblAuditTrailWebService;
import com.ccys.db.vo.discount.BinNumberPageQueryVo;
import com.ccys.db.vo.discount.ServicesAndPackagesVo;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @program: WhiteCoat
 * @description: BIN编号接口实现类
 * @author: ZhangJingCan
 * @create: 2023-12-15 09:49
 **/

@Service
public class BinNumberServiceImpl extends BaseServiceImpl<TblBinNumber> implements BinNumberService {

    @Resource
    private TblBinNumberMapper tblBinNumberMapper;

    @Resource
    private TblBinNumberServiceMapper tblBinNumberServiceMapper;

    @Autowired(required = false)
    private BinNumberServiceService binNumberServiceService;

    /**
     * Services
     */
    @Resource
    private TblMedicalServiceMapper tblMedicalServiceMapper;

    /**
     * Packages
     */
    @Resource
    private TblPackageMapper tblPackageMapper;

    /**
     * 用于保存修改状态日志
     */
    @Autowired(required = false)
    private BaseTblAuditTrailWebService baseTblAuditTrailWebService;

    @Override
    public ResponseResult<ServicesAndPackagesVo, Object> findListServicesAndPackages(String groupId) {
        if (ObjectUtil.isEmpty(groupId)) {
            return ResponseResult.error("Parameter Error!");
        }
        //查询Services
        Example servicesExample = new Example(TblMedicalService.class);
        servicesExample.createCriteria()
                .andEqualTo("groupId", groupId)
                .andEqualTo("status", 1)
                .andEqualTo("delFlag", 0);
        ServicesAndPackagesVo vo = new ServicesAndPackagesVo();
        //放入返回对象
        vo.setServices(tblMedicalServiceMapper.selectByExample(servicesExample));

        //查询Packages
        Example packageExample = new Example(TblPackage.class);
        packageExample.createCriteria().andEqualTo("status", 1).andEqualTo("delFlag", 0);
        vo.setPackages(tblPackageMapper.selectByExample(packageExample));
        return ResponseResult.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult saveBinNumber(BinNumberDto dto) throws ParseException {
        //校验必传字段
        Kit.allParamValid(dto, "name", "status", "startDate", "number", "limitUsage"
                , "discountType", "reusable", "discountAmount", "discountLabel", "afterHoursConsultFloor"
                , "officeHoursConsultFloor", "expired", "discountOffService");
        //校验discountOffService 为1的时候必须传入discountAmountService以及services集合
        if (dto.getDiscountOffService().equals(1)) {
            if (ObjectUtil.isEmpty(dto.getDiscountAmountService())) {
                return ResponseResult.error("Please enter $Off services!");
            }
            if (ObjectUtil.isEmpty(dto.getServices())) {
                return ResponseResult.error("When 'Discount off service' is set to 'yes', please select' services'");
            }
        }

        //判断新增/修改
        if (ObjectUtil.isEmpty(dto.getId())) {
            //新增
            tblBinNumberMapper.insertSelective(dto);

        } else {
            //修改前需要删除services表中所有当前ID的数据 - 副表使用的真删
            Example example = new Example(TblBinNumberService.class);
            example.createCriteria().andEqualTo("binId", dto.getId());
            tblBinNumberServiceMapper.deleteByExample(example);
            //修改本表数据
            tblBinNumberMapper.updateByPrimaryKeySelective(dto);
        }

        //操作副表数据
        //校验discountOffService 为1 去新增services表数据
        if (dto.getDiscountOffService().equals(1)) {
            List<TblBinNumberService> services = dto.getServices();
            for (TblBinNumberService service : services) {
                service.setBinId(dto.getId());
                service.preInsert();
            }
            //循环添加services表数据
            binNumberServiceService.insertAll(services);
        }
        return ResponseResult.success("Save successful!");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteBinNumber(BinNumberDto dto) {
        //判断
        if (ObjectUtil.isEmpty(dto.getId())) {
            return ResponseResult.error("Parameter Error!");
        }
        //查询副表是否存在未删除数据 - 存在则不允许删除
        Example example = new Example(TblBinNumberService.class);
        example.createCriteria().andEqualTo("binId", dto.getId()).andEqualTo("delFlag", 0);
        //检查 - 如果副表存在数据 - 返回错误信息提示先删除副表数据
        if (tblBinNumberServiceMapper.selectCountByExample(example) > 0) {
            return ResponseResult.error("The current data contains undeleted medical service data. Please delete the medical service data first!");
        }

        //准备实体类并赋值
        TblBinNumber tblBinNumber = new TblBinNumber();
        tblBinNumber.setId(dto.getId());
        tblBinNumber.setDelFlag(1);
        //判断是否修改成功 - 返回不同状态
        if (tblBinNumberMapper.updateByPrimaryKeySelective(tblBinNumber) > 0) {
            return ResponseResult.success("Delete Successful!");
        }
        return ResponseResult.error("Delete Failed!");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult updateBinNumberStatus(BinNumberDto dto) {
        //校验
        if (ObjectUtil.isEmpty(dto.getId()) || ObjectUtil.isEmpty(dto.getStatus())) {
            return ResponseResult.error("Parameter Error!");
        }
        //准备数据修改
        TblBinNumber tblBinNumber = new TblBinNumber();
        tblBinNumber.setId(dto.getId());
        tblBinNumber.setStatus(dto.getStatus());
        if (tblBinNumberMapper.updateByPrimaryKeySelective(tblBinNumber) > 0) {
            baseTblAuditTrailWebService.saveStatusLog(dto, dto.getStatus());
            return ResponseResult.success("Modified successfully!");
        }
        return ResponseResult.error("Modification failed!");
    }

    @Override
    public ResponseResult<PageInfo<BinNumberPageQueryVo>, Object> findPageBinNumber(BinNumberDto dto) {
        //校验值范围 - 不在则赋值null
        dto.setStatus(Optional.ofNullable(dto.getStatus()).filter(s -> s > -1 && s < 2).orElse(null));
        dto.setDiscountType(Optional.ofNullable(dto.getDiscountType()).filter(t -> t > -1 && t < 8).orElse(null));
        //开启分页
        PageDto.startPage();
        List<BinNumberPageQueryVo> list = tblBinNumberMapper.findPageBinNumber(dto);
        PageInfo<BinNumberPageQueryVo> info = new PageInfo<>(list);
        return ResponseResult.success(info);
    }

    @Override
    public ResponseResult<ServicesAndPackagesVo, Object> findServices(BinNumberDto dto) {
        //判断
        if (ObjectUtil.isEmpty(dto.getId())) {
            return ResponseResult.error("Parameter Error!");
        }
        //根据ID查询出副表数据先
        Example example = new Example(TblBinNumberService.class);
        example.createCriteria().andEqualTo("binId").andEqualTo("delFlag", 0);
        List<TblBinNumberService> services = tblBinNumberServiceMapper.selectByExample(example);
        if (ObjectUtil.isEmpty(services)) {
            return null;
        }
        //准备返回的对象
        ServicesAndPackagesVo vo = new ServicesAndPackagesVo();

        //流的方式获取出serviceIds和packageIds集合
        List<String> serviceIds = services.stream().filter(a -> a.getServiceId() != null).map(TblBinNumberService::getServiceId).collect(Collectors.toList());
        List<String> packageIds = services.stream().filter(a -> a.getPackageId() != null).map(TblBinNumberService::getPackageId).collect(Collectors.toList());

        //查询service和package
        Example serviceExample = new Example(TblMedicalService.class);
        serviceExample.createCriteria()
                .andIn("id", serviceIds).andEqualTo("status", 1).andEqualTo("delFlag", 0);
        //查询并放入返回对象内
        vo.setServices(tblMedicalServiceMapper.selectByExample(serviceExample));

        Example packageExample = new Example(TblPackage.class);
        packageExample.createCriteria()
                .andIn("id", packageIds).andEqualTo("status", 1).andEqualTo("delFlag", 0);
        vo.setPackages(tblPackageMapper.selectByExample(packageExample));
        return ResponseResult.success(vo);
    }
}
